package com.kungkhies.mvc.kungkher;

import com.kungkhies.mvc.*;
import java.io.ByteArrayInputStream;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.validation.Valid;

import org.jets3t.service.S3Service;
import org.jets3t.service.acl.AccessControlList;
import org.jets3t.service.acl.GroupGrantee;
import org.jets3t.service.acl.Permission;
import org.jets3t.service.impl.rest.httpclient.RestS3Service;
import org.jets3t.service.model.S3Bucket;
import org.jets3t.service.model.S3Object;
import org.jets3t.service.security.AWSCredentials;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.MultipartFile;

import com.kungkhies.domain.kungkher.Kungkher;
import com.kungkhies.domain.kungkher.KungkherRegoFormObject;
import com.kungkhies.domain.kungkhie.KungkhieSummary;
import com.kungkhies.services.kungkher.KungkherService;
import java.util.Collections;
import org.springframework.beans.factory.annotation.Autowired;

@Controller
@RequestMapping("/kungkhers")
public class KungkherController
{
    private final KungkherService kungkherService;
    //@Value("#{s3Properties['s3.accessKey']}")
    private String s3AccessKey = "foo";
    //@Value("#{s3Properties['s3.secretKey']}")
    private String s3SecretKey = "bar";

    @Autowired
    public KungkherController(KungkherService kungkherService)
    {
        this.kungkherService = kungkherService;
    }

    @RequestMapping(value = "/listKungkhers", method = RequestMethod.GET)
    public String listKungkhers(
            @RequestParam(value = "page", defaultValue = "1") int page,
            @RequestParam(value = "perPage", defaultValue = "10") int perPage,
            Map<String, Object> model)
    {
        List<Kungkher> kungkherList = kungkherService.getAllKungkhers();
        
        Collections.sort(kungkherList, new KungkherComparator());
        
        model.put("kungkhers", kungkherList);
        return "kungkhers/list";
    }

    //<start id="method_new_kungkhie"/> 
    @RequestMapping(method = RequestMethod.GET, params = "new")
    public String createKungkherProfile(Model model)
    {
        model.addAttribute(new KungkherRegoFormObject());
        return "kungkhers/rego";
    }
    //<end id="method_new_kungkhie"/> 

    //<start id="method_addKungkherFromForm"/> 
    @RequestMapping(method = RequestMethod.POST)
    public String addKungkherFromForm(@Valid Kungkher kungkher,
            BindingResult bindingResult,
            @RequestParam(value = "image", required = false) MultipartFile image)
    {

        if (bindingResult.hasErrors())
        {
            return "kungkhers/edit";
        }

        kungkherService.saveKungkher(kungkher);

        try
        {
            if (!image.isEmpty())
            {
                validateImage(image);
                saveImage(kungkher.getId() + ".jpg", image);
            }
        }
        catch (ImageUploadException e)
        {
            bindingResult.reject(e.getMessage());
            return "kungkhers/edit";
        }

        return "redirect:/kungkhers/" + kungkher.getKungkherName();
    }
    //<end id="method_addKungkherFromForm"/> 

    private void saveImage(String filename, MultipartFile image)
            throws ImageUploadException
    {

        try
        {
            AWSCredentials awsCredentials =
                    new AWSCredentials(s3AccessKey, s3SecretKey);
            S3Service s3 = new RestS3Service(awsCredentials);

            S3Bucket imageBucket = s3.getBucket("kungkhieImages");
            S3Object imageObject = new S3Object(filename);

            imageObject.setDataInputStream(
                    new ByteArrayInputStream(image.getBytes()));
            imageObject.setContentLength(image.getBytes().length);
            imageObject.setContentType("image/jpeg");

            AccessControlList acl = new AccessControlList();
            acl.setOwner(imageBucket.getOwner());
            acl.grantPermission(GroupGrantee.ALL_USERS,
                    Permission.PERMISSION_READ);
            imageObject.setAcl(acl);
            s3.putObject(imageBucket, imageObject);
        }
        catch (Exception e)
        {
            throw new ImageUploadException("Unable to save image", e);
        }
    }

    private void validateImage(MultipartFile image)
    {
        if (!image.getContentType().equals("image/jpeg"))
        {
            throw new ImageUploadException("Only JPG images accepted");
        }
    }

    //<start id="method_showKungkherProfile"/> 
    @RequestMapping(value = "/{username}", method = RequestMethod.GET)
    public String showKungkherProfile(@PathVariable String username,
            Model model)
    {
        model.addAttribute(kungkherService.getKungkher(username));
        return "kungkhers/view";
    }
    //<end id="method_showKungkherProfile"/> 

    @RequestMapping(value = "/{username}", method = RequestMethod.GET,
    params = "edit")
    public String editKungkherProfile(@PathVariable String username,
            Model model)
    {
        model.addAttribute(kungkherService.getKungkher(username));
        return "kungkhers/edit";
    }

    @RequestMapping(value = "/{username}", method = RequestMethod.PUT)
    public String updateKungkherFromForm(@PathVariable String username, Kungkher kungkher)
    {
        kungkherService.saveKungkher(kungkher);
        return "redirect:/kungkhers/" + username;
    }

    @RequestMapping(value = "/{username}", method = RequestMethod.DELETE)
    public String deleteKungkher(@PathVariable String username)
    {
        // TODO: Add method to remove kungkhie
        //       Probably need to logout here, too...if the deleted user is the authenticated user
        return "redirect:/home";
    }

    @RequestMapping(value = "/{username}/kungkhies",
    method = RequestMethod.GET)
    public String listKungkhiesForKungkher(
            @PathVariable String username, Model model)
    {
        model.addAttribute(kungkherService.getKungkher(username));
        List<KungkhieSummary> kungkhiesForKungkher = kungkherService.getKungkhiesForKungkher(username);
        model.addAttribute(kungkhiesForKungkher);
        return "kungkhies/list";
    }

    
    @RequestMapping(method = RequestMethod.GET,
    headers = "Accept=application/json")
    public @ResponseBody
    List<Kungkher> allKungkhers()
    {
        return kungkherService.getAllKungkhers();
    }

    @RequestMapping(method = RequestMethod.POST,
    headers = "Content-Type=application/json")
    @ResponseStatus(HttpStatus.CREATED)
    public @ResponseBody
    Kungkher createKungkher(@RequestBody Kungkher kungkhie)
    {
        kungkherService.saveKungkher(kungkhie);
        return kungkhie;
    }

    //<start id="method_getKungkher_ResponseBody"/> 
    @RequestMapping(value = "/{username}", method = RequestMethod.GET,
    headers =
    {
        "Accept=text/xml, application/json"
    })
    public @ResponseBody
    Kungkher getKungkher(@PathVariable String username)
    {
        return kungkherService.getKungkher(username);
    }
    //<end id="method_getKungkher_ResponseBody"/> 

//  @RequestMapping(value = "/{username}", method = RequestMethod.GET, 
//          headers = "Accept=application/json")
//  public @ResponseBody 
//    Kungkher getKungkherAsXML(@PathVariable String username) {
//    return kungkherService.getKungkher(username);
//  }
    //<start id="method_putKungkher"/> 
    @RequestMapping(value = "/{username}", method = RequestMethod.PUT, headers = "Content-Type=application/json")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void updateKungkher(@PathVariable String username, @RequestBody Kungkher kungkher)
    {
        kungkherService.saveKungkher(kungkher);
    }
    //<end id="method_putKungkher"/> 

    @RequestMapping(value = "/{username}/kungkhies",
    method = RequestMethod.GET,
    headers = "Accept=application/json")
    public @ResponseBody
    List<KungkhieSummary> getKungkhiesForKungkher(@PathVariable String username)
    {
        return kungkherService.getKungkhiesForKungkher(username);
    }
}
